package com.hyts.bmsp.jfinal.scanner01;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.hyts.bmsp.jfinal.annotations.WebMapping;
import com.hyts.bmsp.jfinal.annotations.WebRoute;
import com.hyts.bmsp.jfinal.beans.WebMappingBean;
import com.hyts.bmsp.jfinal.beans.WebRouteBean;
import com.hyts.bmsp.jfinal.processor.JfinalClassProcessor;
import com.hyts.bmsp.jfinal.processor.classAttribute;
import com.hyts.bmsp.listener.SystemInitalListener;
import com.hyts.bmsp.tool.JarClassLoader;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;

/**
 * @ClassName: _0LoadClassScanner
 * @Description: 加载Class类Scanner扫描器<br>
 * 				  加载指定包中的类扫描器以及对应的信息<br>
 * 				 技术方面采用了FileNameFilter过滤器去扫描文件下面的数据<br>
 * @author: libo
 * @date: 2017年1月12日 下午1:46:05
 */
public final class JfinalClassScanner {
	
	/**
	 * @fieldName: logger
	 * @fieldType: Logger
	 * @Description: 日志输出器
	 */
	private static final Logger logger = Logger.getLogger(JfinalClassProcessor.class.getName());
	/**
	 * @fieldName: classMapping
	 * @fieldType: Map<String,Class<?>>
	 * @Description: class映射关系对象集合容器
	 */
	private Map<String,Class<?>> classMapping = new HashMap<String,Class<?>>();
	
	/**
	 * @fieldName: loadClassFilter
	 * @fieldType: FilenameFilter
	 * @Description: 文件名称过滤器：用于扫描过滤对应的文件名称
	 */
	private FilenameFilter loadClassFilter;
	/**
	 * @fieldName: FILE_PROTOCOL
	 * @fieldType: String
	 * @Description: TODO
	 */
	public static final String FILE_PROTOCOL = "file://";
	
	public static final String PACKAGE_PREFIX = SystemInitalListener.FULL_CONTEXT_PATH;

	public static final String PACKAGE_SUBFIX = "WEB-INF"+File.separator+"classes"+File.separator;//Thread.currentThread().getContextClassLoader().getResource("").getFile().substring(Thread.currentThread().getContextClassLoader().getResource("").getFile().lastIndexOf("/"));

	/**
	 * @Title:_0LoadClassScanner
	 * @Description:扫描方法构造器
	 */
	private JfinalClassScanner() {
		loadClassFilter = new FilenameFilter(){
			@Override
			//排除内部类以及*特殊符号
			public boolean accept(File dir, String name) {
				return !(name.contains("$"));
			}
		};
	}
	
	/**
	 * @Title: getRootFilePath
	 * @Description: 获取根目录路径
	 * @param packagePath
	 * @return
	 * @return: String
	 */
	public String getRootFilePath(String packagePath){
		if(StringUtils.isNotEmpty(packagePath)){
			packagePath = StringUtils.replace(packagePath,".","/");
			return Thread.currentThread().getContextClassLoader().getResource(packagePath).getFile();
		}
		return null;
	}
	
	/**
	 * @Title: getRootFilePath
	 * @Description: 获取根目录路径
	 * @param packagePath
	 * @return
	 * @return: String
	 */
	public static String getClassPackage(String packagePath){
		if(StringUtils.isNotEmpty(packagePath)){
			if(packagePath.indexOf("/") > 0)
			{
				packagePath = StringUtils.replace(packagePath,"/",".");
			}
			else
				packagePath = StringUtils.replace(packagePath,File.separator,".");
			return packagePath;
		}
		return null;
	}
	
	/**
	 * @Title: scannerClassCount
	 * @Description: 扫描并且统计Class类的数量:利用递归的方法
	 * @param filePath
	 * @return
	 * @return: Integer
	 */
	@SuppressWarnings("unchecked")
	private void scanner(String filePath) throws IOException {
		if(StringUtils.isNotEmpty(filePath) ){
			File dir = new File(filePath);
			if(dir.exists()){
				try {
					File[] files = dir.listFiles(loadClassFilter);
					for(File file:files){
						if(file != null && file.isDirectory()){
							scanner(file.getAbsolutePath());
						}else{
							File filet = new File(file.getAbsolutePath());
							if(filet.getAbsolutePath().endsWith(classAttribute.COMPILE.getValue())){
								Class<?> clazz = ClassUtils.getClass(getClassPackage(StringUtils.replace(StringUtils.replace(file.getPath(),PACKAGE_PREFIX+PACKAGE_SUBFIX,""),classAttribute.COMPILE.getValue(),"")));
								if(clazz.getAnnotation(WebMapping.class)  != null) {
									JfinalClassProcessor.processMapping(clazz);
								}
								else if(clazz.getAnnotation(WebRoute.class) != null) {
									JfinalClassProcessor.processRoute(clazz);
								}
								else if(clazz.isEnum()) {
									continue;
								}
								else if(clazz.isAnnotation()) {
									continue;
								}
								else if(clazz.isInterface()) {
									continue;
								}
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * @fieldName: scanner
	 * @fieldType: LoadClassScanner
	 * @Description: TODO
	 */
	private static final JfinalClassScanner scanner = new JfinalClassScanner();

	/**
	 * @Title: doScanner
	 * @Description: 执行scanner扫描操作
	 * @param basePackage
	 * @return
	 * @return: LoadClassScanner
	 */
	public static JfinalClassScanner doScanner(String basePackage) {
		try {
			scanner.scanner(scanner.getRootFilePath(basePackage));
			JarClassLoader.loadClass(scanner.getRootFilePath(basePackage));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return scanner;
	}

	/**
	 * @fieldName: routesList
	 * @fieldType: List<WebRouteBean>
	 * @Description: route路由信息集合列表
	 */
	private static List<WebRouteBean<?>> routesList = new ArrayList<WebRouteBean<?>>();
	
	/**
	 * @fieldName: mappingsList
	 * @fieldType: List<WebMappingBean<?>>
	 * @Description: mapping 实体类与数据库进行关系映射
	 */
	private static List<WebMappingBean<?>> mappingsList = new ArrayList<WebMappingBean<?>>();
	
	/**
	 * @Title: getRoutesList
	 * @Description: TODO
	 * @return
	 * @return: List<WebRouteBean<?>>
	 */
	public static List<WebRouteBean<?>> getRoutesList() {
		return routesList;
	}

	/**
	 * @Title: getMappingsList
	 * @Description: TODO
	 * @return
	 * @return: List<WebMappingBean<?>>
	 */
	public static List<WebMappingBean<?>> getMappingsList() {
		return mappingsList;
	}
	
}
